home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / Papers / C++ Exceptions / µShell / Core Utilities / Debugging / Debugger.cp next >
Encoding:
Text File  |  1998-03-01  |  13.6 KB  |  523 lines  |  [TEXT/CWIE]

  1. //----------------------------------------------------------------------------------------
  2. // UDebug.cp
  3. // Copyright 1984-1994 Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #ifndef __DEBUGGER__
  7. #include "Debugger.h"
  8. #endif
  9.  
  10. #if qDebug || qTheDebugger
  11.     #ifndef __LOWMEM__
  12.     #include <LowMem.h>
  13.     #endif
  14. #endif
  15.  
  16. #if qAppleANSI
  17. #include "UDevConsole.h"
  18. #endif
  19. #include "TheDebugger.h"
  20.  
  21. #include "ClassDesc.h"
  22. #include "DebugWrite.h"
  23.  
  24. #include <Processes.h>
  25.  
  26. //----------------------------------------------------------------------------------------
  27. // Procedure pointer typedefs
  28. //----------------------------------------------------------------------------------------
  29.  
  30. #if qDebug || qTheDebugger
  31.  
  32. typedef long(*GetProcPtr)(Ptr buffer, long count);
  33. typedef void(*PutProcPtr)(Ptr buffer, long count);
  34.  
  35. #endif    // qDebug || qTheDebugger
  36.  
  37. bool gHighLevelDebuggerRunning    = false;            // True if we were able to launch
  38.                                                     // SourceBug, Sade OR Jasik running
  39.  
  40. #if qTheDebugger
  41.  
  42. bool gTheDebuggerIsInstalled    = false;    
  43.  
  44. #endif    // qDebug || qTheDebugger
  45.  
  46.  
  47. //----------------------------------------------------------------------------------------
  48. // Static variable definitions.
  49. //----------------------------------------------------------------------------------------
  50.  
  51. #if qDebug || qTheDebugger
  52.  
  53. static GetProcPtr pGetProc = NULL;                // Address of the Proc to Handle
  54.                                                 // Read requests Function
  55.                                                 // DEVGETTEXT(textBuf: Ptr, byteCount:
  56.                                                 // longint): longint;
  57.  
  58. static PutProcPtr pPutProc = NULL;                // Address of the Proc to Handle
  59.                                                 // WriteLn requests Procedure
  60.                                                 // DEVPUTTEXT(textBuf: Ptr, byteCount:
  61.                                                 // longint);
  62.  
  63. static Boolean pUDebugInitialized = false;        // True if InitUDebug has been called
  64.  
  65. #endif    // qDebug || qTheDebugger
  66.  
  67. #if qDebug
  68.  
  69. static ProcessSerialNumber pPsn;                // The process number of the high level
  70.                                                 // debugger if there is one.
  71.  
  72. #endif    // qDebug
  73.  
  74.  
  75. //----------------------------------------------------------------------------------------
  76. // Forward function declarations
  77. //----------------------------------------------------------------------------------------
  78.  
  79. #if qDebug || qTheDebugger
  80. void InstallWriteLnHook();
  81. #endif
  82.  
  83. //========================================================================================
  84. // GLOBAL Procedures
  85. //========================================================================================
  86. #undef Inherited
  87.  
  88. //----------------------------------------------------------------------------------------
  89. // InitUDebug: essential initialization (segTable, nonRes left in for compatibility (2.0)
  90. //----------------------------------------------------------------------------------------
  91. #pragma segment MAInit
  92.  
  93. #if qDebug || qTheDebugger
  94.  
  95. void InitializeDebugger()
  96. {
  97.     if (qTheDebugger && TheDbgr_IsInstalled()) 
  98.     {
  99. #if qTheDebugger
  100.         gHighLevelDebuggerRunning    = true;
  101.         gTheDebuggerIsInstalled        = true;
  102.         
  103. #if qAppleANSI
  104.         InstallWriteLnHook();
  105. #endif
  106.  
  107.         SetDebugWriteProc(StdDebugWriteProc);
  108.  
  109.         TheDbgr_Adjust_ClassDescr_Ids(ClassDesc::GetClassList());
  110.         TheDbgr_Init_Ext_Dbgr();        // Initialize Hooks for Jasik
  111.  
  112. #endif
  113.     }
  114. #if qDebug && !defined(__PowerPlant__)
  115.     else
  116.     {
  117.         gHighLevelDebuggerRunning = false;
  118.  
  119.         int implement_other_debuggers;
  120. /*    
  121.         if (gConfiguration.hasProcessMgr) {
  122.         
  123.             // First, check to see if the NutraBug Nub exists.
  124.             if ( NubIsInstalled() )
  125.                 gHighLevelDebuggerRunning = true;
  126.             else {
  127.                 // Check to see if one of the high level debuggers are running (SourceBug or Sade). If
  128.                 // so then we will send debug output to it.
  129.                 
  130.                 OSErr err = FindProcessBySignature('Objr', pPsn, NULL);        // Is SourceBug running?
  131.                 if (err != noErr)
  132.                     err = FindProcessBySignature('sade', pPsn, NULL);    // Is Sade running?
  133.                 gHighLevelDebuggerRunning = err == noErr ? true : false;
  134.             }
  135.         }
  136.         else
  137.             gHighLevelDebuggerRunning = System6HasDebugger();        // call System 6 debugger existence test
  138.             
  139.         macroDontDeadStrip(TDebugFlagsView);
  140.         InstallWriteLnHook();
  141. */
  142.  
  143.     }
  144. #endif
  145.     
  146.     pUDebugInitialized = true;
  147. } // InitUDebug
  148.  
  149. #endif    // qDebug || qTheDebugger
  150.  
  151. //----------------------------------------------------------------------------------------
  152. // DebugTerminate:
  153. //----------------------------------------------------------------------------------------
  154.  
  155. #if qDebug || qTheDebugger
  156.  
  157. void FinalizeDebugger()
  158. {
  159. #if qPerform
  160.     // Make sure the performance tools are shut down if they are initialized 
  161.     if (pTP2PerfGlobals)
  162.         TerminatePerfMonitor();
  163. #endif
  164. } // DebugTerminate
  165.  
  166. #endif    // qDebug
  167.  
  168. //----------------------------------------------------------------------------------------
  169. // DebugCanReadLn: Returns true if you can readln to the user
  170. //----------------------------------------------------------------------------------------
  171. #pragma segment Main
  172.  
  173. #if qDebug && !defined(__PowerPlant__)
  174.  
  175. bool DebugCanReadLn()
  176. {
  177.     return false;
  178. } // DebugCanReadLn
  179.  
  180. #endif    // qDebug
  181.  
  182. //----------------------------------------------------------------------------------------
  183. // DebugCanWriteLn: Returns true if you can writeln to the user
  184. //----------------------------------------------------------------------------------------
  185. #pragma segment Main
  186.  
  187. #if qDebug && !defined(__PowerPlant__)
  188.  
  189. bool DebugCanWriteLn()
  190. {
  191.     return pUDebugInitialized;
  192. } // DebugCanWriteLn
  193.  
  194. #endif
  195.  
  196. //----------------------------------------------------------------------------------------
  197. // EachFrameDo:
  198. //----------------------------------------------------------------------------------------
  199. #pragma segment MAUtilitiesRes
  200.  
  201. #if qDebug && !defined(__PowerPlant__)
  202. /*
  203. void EachFrameDo(CStackFrame baseFrame,
  204.                  DoToFrameType DoToFrame,
  205.                  void* staticLink)
  206. {
  207.     CStackFrameIterator iter(baseFrame);
  208.     CStackFrame frame;
  209.     
  210.     for (frame = iter.FirstFrame(); iter.More(); frame = iter.NextFrame())
  211.     {
  212.         DoToFrame(frame, staticLink);
  213.     }
  214. } // EachFrameDo
  215. */
  216. #endif    // qDebug
  217.  
  218. //----------------------------------------------------------------------------------------
  219. // GetCallersMethodName:
  220. //----------------------------------------------------------------------------------------
  221. #pragma segment Main
  222.  
  223. #if qDebug && !defined(__PowerPlant__)
  224. /*
  225. void GetCallersMethodName(MAName& s)
  226. {
  227. #if qPowerPC
  228.     s = "PowerPC";
  229. #else
  230.     CStackFrame stackFrame(GetCurStackFramePtr());
  231.     GetMethodName(stackFrame.GetReturnAddress(), s); // report about our caller"s caller 
  232. #endif
  233. } // GetCallersMethodName
  234. */
  235. #endif    // qDebug
  236.  
  237. //----------------------------------------------------------------------------------------
  238. // GetMethodName: GetMethodName returns the name of the method (or procedure) in which pc
  239. // points.
  240. //----------------------------------------------------------------------------------------
  241. #pragma segment Main
  242.  
  243. #if qDebug && !defined(__PowerPlant__)
  244. /*
  245. void GetMethodName(void* pc, MAName& s)
  246. {
  247.     MAName    discardStr;
  248.     GetProcName(pc, discardStr, s);
  249. } // GetMethodName
  250. */
  251. #endif    // qDebug
  252.  
  253. //----------------------------------------------------------------------------------------
  254. // GetProcName: GetProcName returns the name of the procedure or function in which pc
  255. // points. If it is in a method, then it return"s the name of the method"s class in
  256. // className.
  257. //----------------------------------------------------------------------------------------
  258. #pragma segment Main
  259.  
  260. #if qDebug && !defined(__PowerPlant__)
  261. /*
  262. void GetProcName(void* pc, ClassName& className, MAName& procName)
  263. {
  264. #if !qPowerPC
  265.     if (pc != NULL && !odd((long) pc))
  266.     {
  267.         void* nextPC;
  268.         CStr255 localProcName;
  269.  
  270.         Ptr limit = (Ptr) ((ptrdiff_t) pc + 32767);
  271.         while (!endOfModule(pc, limit, (char *) &localProcName, &nextPC))
  272.         {
  273.             if (pc >= limit)
  274.             {
  275.                 className = "";
  276.                 procName = "";
  277.                 localProcName = "";
  278.                 return;
  279.             }
  280.             else
  281.                 pc = (void *) ((ptrdiff_t) pc + 2);
  282.         }
  283.  
  284.         char cProcName[256];
  285.  
  286.         if (unmangle(cProcName, (char *) localProcName, 255) < 1)
  287.             procName = localProcName;
  288.         else
  289.             procName = cProcName;
  290.  
  291.         short index = procName.Pos(".");
  292.         if (index != 0)
  293.             className = procName.Copy(1, index - 1);
  294.         else
  295.             className = "";
  296.     }
  297.     else
  298. #endif
  299.     {
  300.         className = "";
  301.         procName = "";
  302.     }
  303. } // GetProcName
  304. */
  305. #endif    // qDebug
  306.  
  307. //----------------------------------------------------------------------------------------
  308. // ShowSegments:
  309. //----------------------------------------------------------------------------------------
  310.  
  311. #if qDebug && !defined(__PowerPlant__)
  312.  
  313. void ShowSegments()
  314. {
  315. #if qSegments
  316.     // Show segment information. if allSegments is true then also show unloaded && purged
  317.  
  318.     short i;
  319.     
  320.     long        codeRes;
  321.     long        nSeg;
  322.     Handle        seg;
  323.     short        id;
  324.     CStr255        name;
  325.     ResType        t;
  326.  
  327.  
  328.     codeRes = 0;                                    // counts size of code segments 
  329.  
  330.     nSeg = GetHandleSize((Handle) gCodeSegs) / sizeof(Handle);
  331.  
  332.     fprintf(stderr, "Total # segments = %d \n" , nSeg);
  333.     fprintf(stderr, "• = resident, L = loaded\n");
  334.  
  335.     for (i=0; i<nSeg; i++)
  336.     {
  337.     
  338.         seg = (*gCodeSegs)[i];
  339.         if ((seg != 0) && !IsHandlePurged(seg) && IsHandleLocked(seg))
  340.         {
  341.             GetResInfo(seg, &id, &t, name);
  342.  
  343.             WritePtr((long) seg);
  344.  
  345.             fprintf(stderr, "  Seg#:%d ", id);
  346.  
  347.             if ((*gIsResidentSeg)[i])
  348.                 fprintf(stderr, "• ");
  349.             else if (IsHandlePurged(seg))
  350.                 fprintf(stderr, "  ");
  351.             else if ((*gIsLoadedSeg)[i])
  352.                 fprintf(stderr, "L ");
  353.  
  354.             fprintf(stderr, " %s ", (char *) name);
  355.  
  356.             fprintf(stderr, "%ld bytes\n", (*pSegSize)[i]);
  357.  
  358.             codeRes = codeRes + (*pSegSize)[i] + 8;
  359.         }
  360.     }
  361.  
  362.     fprintf(stderr, "\n");
  363.     fprintf(stderr, "Total loaded code = %ld\n", codeRes);
  364.  
  365.     long lockedSpace = TotalTempSize(true, seg);
  366.     long totalSpace = TotalTempSize(false, seg);
  367.     fprintf(stderr,"  Current temp space: locked = %ld, unlocked = %ld, total = %ld\n",
  368.             lockedSpace, totalSpace - lockedSpace, totalSpace);
  369. #endif
  370. } // ShowSegments
  371.  
  372. #endif    // qDebug
  373.  
  374. //----------------------------------------------------------------------------------------
  375. // System6HasDebugger:
  376. //----------------------------------------------------------------------------------------
  377. #pragma segment Main
  378.  
  379. #if !defined(__MWERKS__)
  380. #if qDebug || qTheDebugger && !defined(__PowerPlant__)
  381.  
  382. Boolean System6HasDebugger()
  383. {
  384. #if qPowerPC
  385.     return false;
  386. #else
  387.     const long* kTrap5Vector = (long *)0x94;        // 680X0 TRAP #5 Vector
  388.     
  389.     // Check to see if the TRAP #5 vector points between A5 and BufPtr.
  390.     // This would imply that it is pointing into MultiFinder's jumptable,
  391.     // which would indicate that Sade or SourceBug is running
  392.     return (*kTrap5Vector > (long)LMGetCurrentA5() && *kTrap5Vector < (long)LMGetBufPtr());
  393. #endif
  394. }
  395.  
  396. #endif    // qDebug || qTheDebugger
  397. #endif    // !defined(__MWERKS__)
  398.  
  399. //----------------------------------------------------------------------------------------
  400. // ConfirmHighLevelDebugger:
  401. //----------------------------------------------------------------------------------------
  402. #pragma segment Main
  403.  
  404. #if qDebug || qTheDebugger
  405.  
  406. #if defined(__MWERKS__) && !defined(__SC__)
  407. #pragma require_prototypes off
  408. #endif
  409.  
  410. bool ConfirmHighLevelDebugger()
  411. {
  412.     if ( qTheDebugger && (gTheDebuggerIsInstalled || TheDbgr_IsInstalled()))
  413.         gHighLevelDebuggerRunning = true;
  414.         
  415. #if qDebug && !defined(__PowerPlant__)
  416.     else if (gHighLevelDebuggerRunning)
  417.     {
  418. /*
  419.         if (gConfiguration.hasProcessMgr)
  420.         {
  421.             if ( NubIsInstalled() )
  422.                 gHighLevelDebuggerRunning = true;
  423.             else
  424.             {
  425.                 OSErr err;
  426.                 ProcessInfoRec processInfo;
  427.                 
  428.                 // Check to see if the high level debugger is still running. The user could have
  429.                 // closed the application. If it is no longer running then just quit sending
  430.                 // output to the debugger.
  431.                 
  432.                 processInfo.processInfoLength = sizeof(ProcessInfoRec);
  433.                 processInfo.processName = NULL;
  434.                 processInfo.processAppSpec = NULL;
  435.                 
  436.                 err = GetProcessInformation(&pPsn, &processInfo);
  437.                 if (err != noErr)
  438.                     gHighLevelDebuggerRunning = false;
  439.             }
  440.         }
  441.         else
  442.             gHighLevelDebuggerRunning = System6HasDebugger();
  443. */
  444.         return false;
  445.     }
  446. #endif
  447.  
  448.     return gHighLevelDebuggerRunning;
  449. } // ConfirmHighLevelDebugger
  450.  
  451. #endif    // qDebug || qTheDebugger
  452.  
  453. //----------------------------------------------------------------------------------------
  454. // DebugWriteLnHook:
  455. //----------------------------------------------------------------------------------------
  456.  
  457. #if qDebug || qTheDebugger
  458.  
  459. void DebugWriteLnHook(Ptr textBuf, long byteCount)
  460. {
  461.     if (ConfirmHighLevelDebugger())
  462.     {        
  463.         Str255 debugStr;
  464.  
  465.         Ptr p = textBuf;
  466.         
  467.         while (byteCount > 0) 
  468.         {
  469.             long len = byteCount;
  470.             
  471.             if (len > 255)
  472.             {
  473.                 len = 255;
  474.             }
  475.             
  476.             debugStr[0] = (unsigned char) len;
  477.  
  478.             BlockMove(p, &debugStr[1], len);
  479.  
  480.             SysBreakFunc(debugStr);
  481.  
  482.             byteCount -= len;
  483.             p += len;
  484.         }
  485.     }
  486. } // DebugWriteLnHook
  487.  
  488. #endif // qDebug || qTheDebugger
  489.  
  490. //----------------------------------------------------------------------------------------
  491. // InstallWriteLnHook:
  492. //----------------------------------------------------------------------------------------
  493.  
  494. #if qAppleANSI
  495.  
  496. void InstallWriteLnHook()
  497. {
  498. #if !(THINK_CPLUS || SYMANTEC_CPLUS)
  499. #if defined(__MWERKS__) && wantDebugging && defined(__CW5__)
  500.     CWInstallWriteLnHook();
  501. #else
  502. #if !defined(__MWERKS__)
  503.     fclose(stdin);
  504.     fclose(stdout);
  505.     fclose(stderr);
  506. #endif
  507.     const short _CODEV = 1;                        // console device number
  508.     _addDevHandler(_CODEV, 0, DevFAccess, DevClose, DevRead, DevWrite, DevIoctl);
  509. #if !defined(__MWERKS__)
  510.     freopen("dev:console", "r", stdin);
  511.     freopen("dev:console", "a", stdout);
  512.     freopen("dev:console", "a", stderr);
  513. #endif
  514.     SetPutProc(DebugWriteLnHook);
  515.     setvbuf(stderr, NULL, _IOLBF, 128);
  516.     SetGetProc(DebugReadLn);
  517. #endif
  518. #endif    // !THINK_CPLUS || SYMANTEC_CPLUS
  519. } // InstallWriteLnHook
  520.  
  521. #endif // qDebug || qTheDebugger
  522.  
  523.